﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using TradingApp.Helper;
using TradingAppDal;
using TradingApp.Properties;
using System.Collections.Concurrent;
using System.Threading;
using System.Data.SqlTypes;
using TradingApp.Data;
using WC.Taxation;

namespace TradingApp
{
    public partial class frmMainApp : Form
    {
        object objLock = new object();
        BindingList<EntityDal> lstEntityToProcess = new BindingList<EntityDal>();
        BindingList<SecurityDal> lstSecuritiesToProcess = new BindingList<SecurityDal>();
        BindingList<EntityDal> lstEntityInProcess = new BindingList<EntityDal>();
        BindingList<SecurityDal> lstSecuritiesInProcess = new BindingList<SecurityDal>();
        BindingList<EntityDal> lstEntityProcessed = new BindingList<EntityDal>();
        BindingList<SecurityDal> lstSecuritiesProcessed = new BindingList<SecurityDal>();
        BindingList<SecurityDal> lstSecuritiesProcessedWithError = new BindingList<SecurityDal>();

        ConcurrentQueue<SecurityDal> SecurityQueueToProcess = new ConcurrentQueue<SecurityDal>();
        ConcurrentDictionary<long, EntityDal> DictEntitiesInQueue = new ConcurrentDictionary<long, EntityDal>();
        ConcurrentDictionary<long, EntityDal> DictEntitiesInProcess = new ConcurrentDictionary<long, EntityDal>();
        ConcurrentDictionary<long, EntityDal> DictEntitiesProcessed = new ConcurrentDictionary<long, EntityDal>();

        object lockInQueue = new object();
        object lockInProcess = new object();
        object lockProcessed = new object();

        ManualResetEvent thread_Pool_wait_handle = new ManualResetEvent(true);
        ManualResetEvent timer_wait_handle = new ManualResetEvent(true);

        System.Threading.Timer DBPoolTimer = null;
        public SynchronizationContext CurrentAppContext;
        int MaxThread = 10;
        List<Thread> lstThreadPool = new List<Thread>();
        bool IsPaused = false;
        bool PoolingOn = false;
        bool IsStopped = false;
        public void SetTimeInterval(int poolInterval)
        {
            //timerDBPool.Interval = poolInterval;
            if (DBPoolTimer != null)
            {
                DBPoolTimer.Change(TradingAppSettings.PoolInterval, TradingAppSettings.PoolInterval);
            }
        }
        public frmMainApp()
        {
            InitializeComponent();
            CurrentAppContext = SynchronizationContext.Current;
            dgvEntitiesInProcess.AutoGenerateColumns = false;
            dgvEntitiesToProcess.AutoGenerateColumns = false;
            dgvEntitiesProcessed.AutoGenerateColumns = false;

            dgvSecuritiesToProcess.AutoGenerateColumns = false;
            dgvSecuritiesInProcess.AutoGenerateColumns = false;
            dgvSecuritiesProcessed.AutoGenerateColumns = false;
            dgvError.AutoGenerateColumns = false;
        }
        private void frmMainApp_Load(object sender, EventArgs e)
        {
            try
            {
                //timerDBPool.Interval = TradingAppSettings.PoolInterval;
                //timerDBPool.Enabled = false;
                MaxThread = TradingAppSettings.MaxThreadCount;
                HandleUI(ThreadingUI.Initial);

                BindGrids();
                LoadInitialData();
                PoolDB(null);
                //ThreadPool.QueueUserWorkItem(PoolDB);

            }
            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }

        private void BindGrids()
        {
            dgvEntitiesToProcess.DataSource = lstEntityToProcess;
            dgvEntitiesInProcess.DataSource = lstEntityInProcess;
            dgvEntitiesProcessed.DataSource = lstEntityProcessed;

            dgvSecuritiesToProcess.DataSource = lstSecuritiesToProcess;
            dgvSecuritiesInProcess.DataSource = lstSecuritiesInProcess;
            dgvSecuritiesProcessed.DataSource = lstSecuritiesProcessed;
            dgvError.DataSource = lstSecuritiesProcessedWithError;
        }

        private void CreateThreadPool()
        {
            for (int i = 0; i < MaxThread; i++)
            {
                Thread poolThread = new Thread(this.StartPoolingToProcessList);
                lstThreadPool.Add(poolThread);
            }
        }


        public void UpdateUI1(object oEntity)
        {
            try
            {
                UIMessage oUIMessage = ((UIMessage)oEntity);
                if (oUIMessage.CurrentAction == UIAction.PoolDBEntityReceieved)
                {
                    //ThreadHelper.AddInToProcessEntityList(lstEntityToProcess, oUIMessage.EntityData);
                }
                if (oUIMessage.CurrentAction == UIAction.PoolDBSecurityReceieved)
                {
                    //ThreadHelper.AddInToProcessSecurityList(lstSecuritiesToProcess, oUIMessage.SecurityData);
                }
                if (oUIMessage.CurrentAction == UIAction.InProcessEntityReceieved)
                {
                    //ThreadHelper.RemoveFromToProcessEntityList(lstEntityToProcess, oUIMessage.EntityData);
                    //ThreadHelper.AddInInProcessEntityList(lstEntityInProcess, oUIMessage.EntityData);
                }
                if (oUIMessage.CurrentAction == UIAction.InProcessSecurityReceieved)
                {
                    //ThreadHelper.RemoveFromToProcessSecurityList(lstSecuritiesToProcess, oUIMessage.SecurityData);
                    //ThreadHelper.AddInInProcessSecurityList(lstSecuritiesInProcess, oUIMessage.SecurityData);
                }
                if (oUIMessage.CurrentAction == UIAction.EntityDirectlyProcessed)
                {
                    //ThreadHelper.RemoveFromToProcessEntityList(lstEntityToProcess, oUIMessage.EntityData);
                    //ThreadHelper.AddInProcessedEntityList(lstEntityProcessed, oUIMessage.EntityData);
                }
                if (oUIMessage.CurrentAction == UIAction.EntityProcessed)
                {
                    //ThreadHelper.RemoveFromInProcessEntityList(lstEntityInProcess, oUIMessage.EntityData);
                    //ThreadHelper.AddInProcessedEntityList(lstEntityProcessed, oUIMessage.EntityData);
                }
                if (oUIMessage.CurrentAction == UIAction.SecurityProcessed)
                {
                    //ThreadHelper.RemoveFromInProcessSecurityList(lstSecuritiesInProcess, oUIMessage.SecurityData);
                    //ThreadHelper.AddInProcessedSecurityList(lstSecuritiesProcessed, oUIMessage.SecurityData);
                }

                Application.DoEvents();
            }
            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }
        public void UpdateUI(object oEntity)
        {
            try
            {
                UIMessage oUIMessage = ((UIMessage)oEntity);
                if (oUIMessage.CurrentAction == UIAction.PoolDBEntityReceieved)
                {
                    ThreadHelper.AddInToProcessEntityList(lstEntityToProcess, oUIMessage.Entitities, DictEntitiesInQueue, gbEntitiesToProcess);

                }
                if (oUIMessage.CurrentAction == UIAction.PoolDBSecurityReceieved)
                {
                    ThreadHelper.AddInToProcessSecurityList(lstSecuritiesToProcess, oUIMessage.Securtities, oUIMessage.EntityData, SecurityQueueToProcess, gbSecuritiesToProcess);

                }
                if (oUIMessage.CurrentAction == UIAction.InProcessEntityReceieved)
                {
                    ThreadHelper.RemoveFromToProcessEntityList(lstEntityToProcess, oUIMessage.EntityData, UIAction.InProcessEntityReceieved, gbEntitiesToProcess);
                    ThreadHelper.AddInInProcessEntityList(lstEntityInProcess, oUIMessage.EntityData, gbEntitiesInProcess);
                }
                if (oUIMessage.CurrentAction == UIAction.InProcessSecurityReceieved)
                {
                    ThreadHelper.RemoveFromToProcessSecurityList(lstSecuritiesToProcess, oUIMessage.SecurityData, gbSecuritiesToProcess);
                    ThreadHelper.AddInInProcessSecurityList(lstSecuritiesInProcess, oUIMessage.SecurityData, gbSecuritiesInProcess);
                }
                if (oUIMessage.CurrentAction == UIAction.EntityDirectlyProcessed)
                {
                    ThreadHelper.RemoveFromToProcessEntityList(lstEntityToProcess, oUIMessage.EntityData, UIAction.EntityDirectlyProcessed, gbEntitiesToProcess);
                    ThreadHelper.AddInProcessedEntityList(lstEntityProcessed, oUIMessage.EntityData, gbEntitiesProcesed);
                }
                if (oUIMessage.CurrentAction == UIAction.EntityProcessed)
                {
                    ThreadHelper.RemoveFromInProcessEntityList(lstEntityInProcess, oUIMessage.EntityData, gbEntitiesInProcess);
                    ThreadHelper.AddInProcessedEntityList(lstEntityProcessed, oUIMessage.EntityData, gbEntitiesProcesed);
                }
                if (oUIMessage.CurrentAction == UIAction.SecurityProcessed)
                {
                    ThreadHelper.RemoveFromInProcessSecurityList(lstSecuritiesInProcess, oUIMessage.SecurityData, gbSecuritiesInProcess);
                    if (oUIMessage.SecurityData.IsError)
                    {
                        ThreadHelper.AddInProcessedWithErrorSecurityList(lstSecuritiesProcessedWithError, oUIMessage.SecurityData, gbError);
                    }
                    else
                    {
                        ThreadHelper.AddInProcessedSecurityList(lstSecuritiesProcessed, oUIMessage.SecurityData, gbSecuritiesProcessed);
                    }
                }
                if (oUIMessage.CurrentAction == UIAction.EntityReProcessed)
                {
                    ThreadHelper.RemoveFromProcessedEntityList(lstEntityProcessed, oUIMessage.EntityData, gbEntitiesProcesed);
                    ThreadHelper.RemoveFromProcessedSecurityList(lstSecuritiesProcessed, oUIMessage.EntityData.Process_ID.Value, gbSecuritiesProcessed);
                }
                if (oUIMessage.CurrentAction == UIAction.SecurityReProcessed)
                {
                    ThreadHelper.RemoveFromProcessedEntityList(lstEntityProcessed, oUIMessage.EntityData, gbEntitiesProcesed);
                    ThreadHelper.RemoveFromProcessedSecurityList(lstSecuritiesProcessed, oUIMessage.SecurityData, gbSecuritiesProcessed);
                }

                Application.DoEvents();
            }
            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }

        private void timerDBPool_Tick(object sender, EventArgs e)
        {
            try
            {
                PoolDB(null);
            }

            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }

        private void PoolDB(object oTimerObj)
        {
            // pool db
            EntityDal oEntityDal = new EntityDal();
            SecurityDal oSecurityDal = new SecurityDal();
            List<EntityDal> lstTempEntityToProcess = oEntityDal.GetEntities(EntityType.ToProcess);

            UIMessage oUIMessage = new UIMessage { CurrentAction = UIAction.PoolDBEntityReceieved, Entitities = lstTempEntityToProcess };
            CurrentAppContext.Send(UpdateUI, oUIMessage);

            // now iterate each entity
            foreach (EntityDal oEntity in lstTempEntityToProcess)
            {
                // now process securities of this entity
                timer_wait_handle.WaitOne();
                if (IsStopped)
                {
                    break;
                }
                oEntity.Securities = oSecurityDal.GetEntitySecurities(oEntity.Process_ID, EntityType.ToProcess);
                if (oEntity.Securities.Count == 0)
                {
                    oEntity.Entities_Processed = DateTime.Now;
                    oEntity.UpdateEntity(oEntity.Process_ID.Value, EntityType.InProcess);
                    oEntity.UpdateEntity(oEntity.Process_ID.Value, EntityType.Processed);
                    UIMessage oEntProcessedUIMessage = new UIMessage { CurrentAction = UIAction.EntityDirectlyProcessed, EntityData = oEntity };
                    CurrentAppContext.Send(UpdateUI, oEntProcessedUIMessage);

                }
                else
                {
                    UIMessage oSecUIMessage = new UIMessage { CurrentAction = UIAction.PoolDBSecurityReceieved, Securtities = oEntity.Securities, EntityData = oEntity };
                    CurrentAppContext.Send(UpdateUI, oSecUIMessage);
                }
            }
            if (SecurityQueueToProcess.Count > 0 && !IsPaused)
            {
                thread_Pool_wait_handle.Set();
            }
        }

        private void PoolDB1(object oTimerObj)
        {
            // pool db
            EntityDal oEntityDal = new EntityDal();
            SecurityDal oSecurityDal = new SecurityDal();
            List<EntityDal> lstTempEntityToProcess = oEntityDal.GetEntities(EntityType.ToProcess);

            foreach (EntityDal oEntity in lstTempEntityToProcess)
            {
                oEntity.Entities_InQue = DateTime.Now;
                oEntity.UpdateEntity(oEntity.Process_ID.Value, EntityType.InQueue);
                lock (lockInQueue)
                {
                    if (!DictEntitiesInQueue.ContainsKey(oEntity.Process_ID.Value))
                    {
                        DictEntitiesInQueue.TryAdd(oEntity.Process_ID.Value, oEntity);
                        UIMessage oUIMessage = new UIMessage { CurrentAction = UIAction.PoolDBEntityReceieved, EntityData = oEntity };
                        CurrentAppContext.Send(UpdateUI, oUIMessage);
                    }
                }
            }

            // now iterate each entity
            foreach (EntityDal oEntity in lstTempEntityToProcess)
            {
                // now process securities of this entity
                timer_wait_handle.WaitOne();
                if (IsStopped)
                {
                    break;
                }
                oEntity.Securities = oSecurityDal.GetEntitySecurities(oEntity.Process_ID, EntityType.ToProcess);
                if (oEntity.Securities.Count == 0)
                {
                    oEntity.Entities_Processed = DateTime.Now;
                    oEntity.UpdateEntity(oEntity.Process_ID.Value, EntityType.InProcess);
                    oEntity.UpdateEntity(oEntity.Process_ID.Value, EntityType.Processed);
                    UIMessage oEntProcessedUIMessage = new UIMessage { CurrentAction = UIAction.EntityDirectlyProcessed, EntityData = oEntity };
                    CurrentAppContext.Send(UpdateUI, oEntProcessedUIMessage);

                }
                foreach (SecurityDal oSecurity in oEntity.Securities)
                {

                    timer_wait_handle.WaitOne();
                    if (IsStopped)
                    {
                        break;
                    }
                    oSecurity.SecGroup_InQue = DateTime.Now;
                    oSecurity.ParentEntity = oEntity;
                    oSecurity.UpdateSecurity(oSecurity.SecOrder_ID.Value, EntityType.InQueue);
                    UIMessage oSecUIMessage = new UIMessage { CurrentAction = UIAction.PoolDBSecurityReceieved, SecurityData = oSecurity };
                    CurrentAppContext.Send(UpdateUI, oSecUIMessage);
                    SecurityQueueToProcess.Enqueue(oSecurity);
                }
            }
            if (SecurityQueueToProcess.Count > 0 && !IsPaused)
            {
                thread_Pool_wait_handle.Set();
            }
        }

        private void StartPoolingToProcessList()
        {
            try
            {
                while (true)
                {
                    thread_Pool_wait_handle.WaitOne();
                    SecurityDal oSecurityToProcess = new SecurityDal();
                    bool IsDequeue = SecurityQueueToProcess.TryDequeue(out oSecurityToProcess);
                    if (IsDequeue)
                    {
                        lock (lockInProcess)
                        {
                            if (!DictEntitiesInProcess.ContainsKey(oSecurityToProcess.ParentEntity.Process_ID.Value))
                            {
                                // update entity
                                DictEntitiesInProcess.TryAdd(oSecurityToProcess.ParentEntity.Process_ID.Value, oSecurityToProcess.ParentEntity);
                                oSecurityToProcess.ParentEntity.Entities_InProcess = DateTime.Now;
                                oSecurityToProcess.ParentEntity.UpdateEntity(oSecurityToProcess.ParentEntity.Process_ID.Value, EntityType.InProcess);
                                UIMessage oEntUIMessage = new UIMessage { CurrentAction = UIAction.InProcessEntityReceieved, EntityData = oSecurityToProcess.ParentEntity };
                                CurrentAppContext.Send(UpdateUI, oEntUIMessage);
                            }
                        }

                        // move security in InProcess Grid
                        oSecurityToProcess.SecGroup_InProcess = DateTime.Now;
                        oSecurityToProcess.UpdateSecurity(oSecurityToProcess.SecOrder_ID.Value, EntityType.InProcess);
                        UIMessage oSecUIMessage = new UIMessage { CurrentAction = UIAction.InProcessSecurityReceieved, SecurityData = oSecurityToProcess };
                        CurrentAppContext.Send(UpdateUI, oSecUIMessage);

                        // now starts the processing - so actual time will be started to calculate from here
                        //AnalysisHelper.AnalyzeSecurity(oSecurityToProcess);
                        try
                        {
                            WCTaxation.AnalyzeSecurity(GetTaxationParam(oSecurityToProcess.SecOrder_ID.Value));
                        }
                        catch (System.Exception ex)
                        {
                            oSecurityToProcess.IsError = true;
                            oSecurityToProcess.ErrorMessage = ex.Message;
                        }
                            


                        oSecurityToProcess.IsProcessingCompleted = true;
                        oSecurityToProcess.SecGroup_Processed = DateTime.Now;
                        oSecurityToProcess.UpdateSecurity(oSecurityToProcess.SecOrder_ID.Value, EntityType.Processed);
                        UIMessage oSecProcessedUIMessage = new UIMessage { CurrentAction = UIAction.SecurityProcessed, SecurityData = oSecurityToProcess };
                        CurrentAppContext.Send(UpdateUI, oSecProcessedUIMessage);


                        lock (lockProcessed)
                        {
                            if (oSecurityToProcess.ParentEntity.IsProcessingCompleted())
                            {
                                if (!DictEntitiesProcessed.ContainsKey(oSecurityToProcess.ParentEntity.Process_ID.Value))
                                {
                                    // update entity
                                    DictEntitiesProcessed.TryAdd(oSecurityToProcess.ParentEntity.Process_ID.Value, oSecurityToProcess.ParentEntity);

                                    oSecurityToProcess.ParentEntity.Entities_Processed = DateTime.Now;
                                    oSecurityToProcess.ParentEntity.UpdateEntity(oSecurityToProcess.Process_ID.Value, EntityType.Processed);
                                    UIMessage oEntProcessedUIMessage = new UIMessage { CurrentAction = UIAction.EntityProcessed, EntityData = oSecurityToProcess.ParentEntity };
                                    CurrentAppContext.Send(UpdateUI, oEntProcessedUIMessage);
                                }
                            }
                        }


                    }
                    else
                    {
                        thread_Pool_wait_handle.Reset();
                    }
                }
            }
            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }

        private WCTaxationParam GetTaxationParam(long SecOrderID)
        {
            SecurityDal oSecurityDal = new SecurityDal();
            oSecurityDal.SecOrder_ID = SecOrderID;
            WCTaxationParam param = new WCTaxationParam();
            param.lstCorpActions = oSecurityDal.GetSecurityCorpActions(oSecurityDal.SecOrder_ID.Value);
            param.lstDividents = oSecurityDal.GetSecurityDividents(oSecurityDal.SecOrder_ID.Value);
            param.lstIdentifiedStraddles = oSecurityDal.GetSecurityIdentifiedStraddles(oSecurityDal.SecOrder_ID.Value);
            param.lstM1s = oSecurityDal.GetSecurityM1Dal(oSecurityDal.SecOrder_ID.Value);
            param.lstSecurities = oSecurityDal.GetSecuritySecMasters(oSecurityDal.SecOrder_ID.Value);

            param.lstInProcessSecurity = oSecurityDal.GetSecurityInProcess(oSecurityDal.SecOrder_ID.Value);
            param.lstTransactions = oSecurityDal.GetSecurityTransactions(oSecurityDal.SecOrder_ID.Value);
            return param;
        }
        private bool IsEntityProcessed(long Process_ID)
        {
            foreach (EntityDal entity in lstEntityProcessed)
            {
                if (entity.Process_ID.Value == Process_ID)
                {
                    return true;
                }
            }
            return false;
        }
        private void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                if (IsStopped)
                {
                    ReInitializeApp();
                }
                StartThreading();

            }
            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }

        private void ReInitializeApp()
        {

            lstEntityToProcess.Clear();
            lstEntityInProcess.Clear();
            lstEntityProcessed.Clear();

            lstSecuritiesToProcess.Clear();
            lstSecuritiesInProcess.Clear();
            lstSecuritiesProcessed.Clear();

            DictEntitiesInQueue.Clear();
            DictEntitiesInProcess.Clear();
            DictEntitiesProcessed.Clear();

            while (true)
            {
                SecurityDal oSecurityDal;
                bool bIsDequeue = SecurityQueueToProcess.TryDequeue(out oSecurityDal);
                if (!bIsDequeue)
                {
                    break;
                }
            }
            //BindGrids();
            LoadInitialData();

        }

        private void LoadInitialData()
        {
            EntityDal oEntityDal = new EntityDal();
            SecurityDal oSecurityDal = new SecurityDal();
            List<EntityDal> tmpLstEntityDal = oEntityDal.GetEntities(EntityType.Processed);
            List<SecurityDal> tmpLstSecurityDal = oSecurityDal.GetSecurities(SqlInt64.Null, EntityType.Processed);
            foreach (EntityDal oEntity in tmpLstEntityDal)
            {
                lstEntityProcessed.Add(oEntity);
                if (!DictEntitiesProcessed.ContainsKey(oEntity.Process_ID.Value))
                {
                    DictEntitiesProcessed.TryAdd(oEntity.Process_ID.Value, oEntity);
                }
            }
            foreach (SecurityDal oSecurity in tmpLstSecurityDal)
            {
                lstSecuritiesProcessed.Add(oSecurity);
            }


            // move InQueue and In Process Securities to ToProcessQueue
            List<SecurityDal> lstTempSecuritiesInQueue = oSecurityDal.GetSecurities(SqlInt64.Null, EntityType.InQueue);
            List<SecurityDal> lstTempSecuritiesInProcess = oSecurityDal.GetSecurities(SqlInt64.Null, EntityType.InProcess);

            List<SecurityDal> lstTempAllSecurities = new List<SecurityDal>(lstTempSecuritiesInQueue);
            lstTempAllSecurities.AddRange(lstTempSecuritiesInProcess);
            Dictionary<long, EntityDal> DictEntities = new Dictionary<long, EntityDal>();
            foreach (SecurityDal oSecurity in lstTempSecuritiesInProcess)
            {
                oSecurity.ParentEntity = GetSecurityParent(DictEntities, oSecurity, lstTempAllSecurities);
                SecurityQueueToProcess.Enqueue(oSecurity);
                lstSecuritiesToProcess.Add(oSecurity);
            }

            foreach (SecurityDal oSecurity in lstTempSecuritiesInQueue)
            {
                oSecurity.ParentEntity = GetSecurityParent(DictEntities, oSecurity, lstTempAllSecurities);
                SecurityQueueToProcess.Enqueue(oSecurity);
                lstSecuritiesToProcess.Add(oSecurity);
            }

            // move InQueue and In Process Entities to ToProcessQueue
            //bind securities as well
            List<EntityDal> lstTempEntityInQueue = oEntityDal.GetEntities(EntityType.InQueue);
            List<EntityDal> lstTempEntityInProcess = oEntityDal.GetEntities(EntityType.InProcess);

            foreach (EntityDal oEntity in lstTempEntityInQueue)
            {
                //oEntity.Securities = GetChildSecurities(oEntity.Process_ID.Value, lstTempAllSecurities);
                if (!DictEntitiesInQueue.ContainsKey(oEntity.Process_ID.Value))
                {
                    DictEntitiesInQueue.TryAdd(oEntity.Process_ID.Value, oEntity);
                    lstEntityToProcess.Add(oEntity);
                }
            }
            foreach (EntityDal oEntity in lstTempEntityInProcess)
            {
                //oEntity.Securities = GetChildSecurities(oEntity.Process_ID.Value, lstTempAllSecurities);
                if (!DictEntitiesInQueue.ContainsKey(oEntity.Process_ID.Value))
                {
                    DictEntitiesInQueue.TryAdd(oEntity.Process_ID.Value, oEntity);
                    lstEntityToProcess.Add(oEntity);
                }
            }
            gbEntitiesToProcess.Text = "Entities To Process - " + lstEntityToProcess.Count;
            gbEntitiesInProcess.Text = "Entities In Process - " + lstEntityInProcess.Count;
            gbEntitiesProcesed.Text = "Entities Processed - " + lstEntityProcessed.Count;

            gbSecuritiesToProcess.Text = "Securities To Process - " + lstSecuritiesToProcess.Count;
            gbSecuritiesInProcess.Text = "Securities In Process - " + lstSecuritiesInProcess.Count;
            gbSecuritiesProcessed.Text = "Securities Processed - " + lstSecuritiesProcessed.Count;
        }

        private EntityDal GetSecurityParent(Dictionary<long, EntityDal> DictEntities, SecurityDal oSecurity, List<SecurityDal> lstAllSecurities)
        {
            EntityDal oParent = null;
            if (DictEntities.ContainsKey(oSecurity.Process_ID.Value))
            {
                oParent = DictEntities[oSecurity.Process_ID.Value];
            }
            else
            {
                oParent = oSecurity.ParentEntity;
                oParent.Securities = GetChildSecurities(oSecurity.Process_ID.Value, lstAllSecurities);
                DictEntities.Add(oSecurity.Process_ID.Value, oParent);
            }
            return oParent;
        }
        private List<SecurityDal> GetChildSecurities(long ProcessId, List<SecurityDal> AllSecurities)
        {
            List<SecurityDal> tempSec = AllSecurities.FindAll(p => p.Process_ID.Value == ProcessId);
            if (null == tempSec)
            {
                tempSec = new List<SecurityDal>();
            }
            return tempSec;
        }
        private void HandlePoolingUI()
        {
            if (PoolingOn)
            {
                lblPoolingStatus.Text = "Current Status : On";
                pbPoolingStatus.Image = Resources.Green;
            }
            else
            {
                lblPoolingStatus.Text = "Current Status : Off";
                pbPoolingStatus.Image = Resources.Red;
            }
        }


        private void StartThreading()
        {
            //timerDBPool.Enabled = true;
            MaxThread = TradingAppSettings.MaxThreadCount;
            CreateThreadPool();
            int StartInterval = TradingAppSettings.PoolInterval;
            if (IsStopped)
            {
                StartInterval = 0;
            }
            DBPoolTimer = new System.Threading.Timer(PoolDB, null, StartInterval, TradingAppSettings.PoolInterval);
            HandleUI(ThreadingUI.Start);
            for (int i = 0; i < MaxThread; i++)
            {
                lstThreadPool[i].Start();
            }
            IsStopped = false;
            //PoolDB();
        }


        private void HandleUI(ThreadingUI oThreadingUI)
        {
            btnPauseContinue.Enabled = false;
            btnStop.Enabled = false;
            btnStart.Enabled = false;
            IsPaused = false;
            PoolingOn = false;
            switch (oThreadingUI)
            {
                case ThreadingUI.Initial:
                    btnStart.Enabled = true;
                    btnPauseContinue.Enabled = false;
                    btnStop.Enabled = false;
                    PoolingOn = false;
                    break;
                case ThreadingUI.Pause:
                    btnStart.Enabled = false;
                    btnPauseContinue.Enabled = true;
                    btnPauseContinue.Text = "Continue";
                    btnStop.Enabled = true;
                    IsPaused = true;
                    PoolingOn = false;
                    break;
                case ThreadingUI.Continue:
                    btnStart.Enabled = false;
                    btnPauseContinue.Enabled = true;
                    btnPauseContinue.Text = "Pause";
                    btnStop.Enabled = true;
                    PoolingOn = true;
                    break;
                case ThreadingUI.Stop:
                    btnStart.Enabled = true;
                    btnPauseContinue.Enabled = false;
                    btnPauseContinue.Text = "Pause";
                    btnStop.Enabled = false;
                    PoolingOn = false;
                    break;
                case ThreadingUI.Start:
                    btnStart.Enabled = false;
                    btnPauseContinue.Enabled = true;
                    btnPauseContinue.Text = "Pause";
                    btnStop.Enabled = true;
                    PoolingOn = true;
                    break;
            }
            HandlePoolingUI();
        }

        private void btnPauseContinue_Click(object sender, EventArgs e)
        {
            try
            {
                if (btnPauseContinue.Text == "Pause")
                {
                    PauseThreading();
                    HandleUI(ThreadingUI.Pause);
                }
                else
                {
                    ContinueThreading();
                    HandleUI(ThreadingUI.Continue);
                }
            }
            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }

        private void PauseThreading()
        {
            //timerDBPool.Enabled = false;
            DBPoolTimer.Change(Timeout.Infinite, Timeout.Infinite);
            timer_wait_handle.Reset();
            thread_Pool_wait_handle.Reset();
        }

        private void ContinueThreading()
        {
            //timerDBPool.Enabled = true;
            DBPoolTimer.Change(TradingAppSettings.PoolInterval, TradingAppSettings.PoolInterval);
            timer_wait_handle.Set();
            thread_Pool_wait_handle.Set();
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            try
            {
                StopThreading();
                HandleUI(ThreadingUI.Stop);
            }
            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }

        private void StopThreading()
        {
            try
            {
                //timerDBPool.Enabled = false;
                IsStopped = true;
                DBPoolTimer.Change(Timeout.Infinite, Timeout.Infinite);
                DBPoolTimer.Dispose();
                DBPoolTimer = null;
                for (int i = 0; i < MaxThread; i++)
                {
                    lstThreadPool[i].Abort();
                    lstThreadPool[i] = null;
                }
                lstThreadPool.Clear();
                timer_wait_handle.Set();
                thread_Pool_wait_handle.Set();
            }
            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }



        private void ShowSecurityMessage(SecurityDal oSecurity)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Security :" + oSecurity.Security_Name + " , Process Id :" + oSecurity.Process_ID);
            if (!oSecurity.SecGroup_InQue.IsNull)
            {
                sb.Append(Environment.NewLine + " Queued at :" + oSecurity.SecGroup_InQue.Value);
            }
            if (!oSecurity.SecGroup_InProcess.IsNull)
            {
                sb.Append(Environment.NewLine + " In Process at :" + oSecurity.SecGroup_InProcess.Value);
            }
            if (!oSecurity.SecGroup_Processed.IsNull)
            {
                sb.Append(Environment.NewLine + " Processed at :" + oSecurity.SecGroup_Processed.Value);
            }
            MessageBox.Show(sb.ToString(), "Security Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void dgvEntitiesProcessed_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                if (e.RowIndex > -1 && e.RowIndex < dgvEntitiesProcessed.Rows.Count)
                {
                    EntityDal oEntityDal = (EntityDal)dgvEntitiesProcessed.Rows[e.RowIndex].DataBoundItem;
                    //frmReporting ofrmReporting = new frmReporting();
                    //ofrmReporting.SetCustomLoad(true,oEntityDal, null, true);
                    //ofrmReporting.ShowDialog();

                    frmTradingAppParent ofrmTradingAppParent = (frmTradingAppParent)this.MdiParent;
                    frmReporting ofrmReporting = ofrmTradingAppParent.GetReportingScreen();
                    ofrmReporting.SetCustomLoad(true, oEntityDal, null, true);
                    ofrmTradingAppParent.OpenReportingScreen();
                }
            }
            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }

        private void ShowEntityMessage(EntityDal oEntity)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Entity :" + oEntity.Entity_Name + " , Process Id :" + oEntity.Process_ID);
            if (!oEntity.Entities_InQue.IsNull)
            {
                sb.Append(Environment.NewLine + " Queued at :" + oEntity.Entities_InQue.Value);
            }
            if (!oEntity.Entities_InProcess.IsNull)
            {
                sb.Append(Environment.NewLine + " In Process at :" + oEntity.Entities_InProcess.Value);
            }
            if (!oEntity.Entities_Processed.IsNull)
            {
                sb.Append(Environment.NewLine + " Processed at :" + oEntity.Entities_Processed.Value);
            }
            MessageBox.Show(sb.ToString(), "Entity Information", MessageBoxButtons.OK, MessageBoxIcon.Information);

        }

        private void dgvSecuritiesProcessed_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                if (e.RowIndex > -1 && e.RowIndex < dgvSecuritiesProcessed.Rows.Count)
                {
                    EntityDal oEntityTemp = new EntityDal();
                    EntityDal oEntityDal;
                    SecurityDal oSecurityDal = (SecurityDal)dgvSecuritiesProcessed.Rows[e.RowIndex].DataBoundItem;
                    if (oSecurityDal.ParentEntity == null)
                    {
                        oEntityDal = oEntityTemp.GetEntityByProcessID(oSecurityDal.Process_ID.Value);
                    }
                    else
                    {
                        oEntityDal = oSecurityDal.ParentEntity;
                    }
                    
                    List<SecurityDal> lstSec = new List<SecurityDal>();
                    lstSec.Add(oSecurityDal);

                    frmTradingAppParent ofrmTradingAppParent = (frmTradingAppParent)this.MdiParent;
                    frmReporting ofrmReporting = ofrmTradingAppParent.GetReportingScreen();
                    ofrmReporting.SetCustomLoad(true,oEntityDal, lstSec, false);
                    ofrmTradingAppParent.OpenReportingScreen();
                }
            }
            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }

        private void cmsProcessedEntity_MouseClick(object sender, MouseEventArgs e)
        {
            try
            {
                if (dgvEntitiesProcessed.SelectedRows.Count > 0)
                {
                    EntityDal tempEntityDal = new EntityDal();
                    EntityDal oEntityDal = (EntityDal)dgvEntitiesProcessed.SelectedRows[0].DataBoundItem;
                    DictEntitiesInQueue.TryRemove(oEntityDal.Process_ID.Value, out tempEntityDal);
                    DictEntitiesInProcess.TryRemove(oEntityDal.Process_ID.Value, out tempEntityDal);
                    DictEntitiesProcessed.TryRemove(oEntityDal.Process_ID.Value, out tempEntityDal);
                    oEntityDal.ReprocessEntity(oEntityDal.Process_ID.Value);
                    UIMessage oEntProcessedUIMessage = new UIMessage { CurrentAction = UIAction.EntityReProcessed, EntityData = oEntityDal };
                    CurrentAppContext.Send(UpdateUI, oEntProcessedUIMessage);
                    PoolDB(null);
                }
                else
                {
                    MessageBox.Show("Please select a row to reprocess.", "Reprocess Entity", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }

        

        private void cmsProcessedSecurity_MouseClick(object sender, MouseEventArgs e)
        {
            try
            {
                if (dgvSecuritiesProcessed.SelectedRows.Count > 0)
                {
                    EntityDal tempEntityDal = new EntityDal();
                    SecurityDal oSecurityDal = (SecurityDal)dgvSecuritiesProcessed.SelectedRows[0].DataBoundItem;
                    if (IsEntityProcessed(oSecurityDal.Process_ID.Value))
                    {
                        if (oSecurityDal.ParentEntity == null)
                        {
                            oSecurityDal.ParentEntity = tempEntityDal.GetEntityByProcessID(oSecurityDal.Process_ID.Value);
                        }
                        DictEntitiesInQueue.TryRemove(oSecurityDal.Process_ID.Value, out tempEntityDal);
                        DictEntitiesInProcess.TryRemove(oSecurityDal.Process_ID.Value, out tempEntityDal);
                        DictEntitiesProcessed.TryRemove(oSecurityDal.Process_ID.Value, out tempEntityDal);
                        oSecurityDal.ReprocessSecurity(oSecurityDal.Process_ID.Value, oSecurityDal.SecOrder_ID.Value);
                        UIMessage oEntProcessedUIMessage = new UIMessage { CurrentAction = UIAction.SecurityReProcessed, EntityData = oSecurityDal.ParentEntity, SecurityData = oSecurityDal };
                        CurrentAppContext.Send(UpdateUI, oEntProcessedUIMessage);
                        PoolDB(null);
                    }
                    else
                    {
                        MessageBox.Show("Security can be reprocessed once entity is completely processed.", "Reprocess Entity", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }
                else
                {
                    MessageBox.Show("Please select a row to reprocess.", "Reprocess Entity", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }

        private void btnRetryAnalysis_Click(object sender, EventArgs e)
        {
            try
            {
                //AnalysisHelper.AnalyzeSecurityByPolark(24);
                WCTaxation.AnalyzeSecurity();
            }
            catch (System.Exception ex)
            {
                UIHelper.HandleApplicationException(ex);
            }
        }

    }
    public class UserEntity
    {
        public int ID { get; set; }
        public string DisplayName { get; set; }
        public string ThreadID { get; set; }
        public override string ToString()
        {
            return DisplayName + "-" + ThreadID;
        }
    }
    public class UIMessage
    {
        public UIAction CurrentAction { get; set; }
        public bool IsCompleted { get; set; }
        public string Message { get; set; }
        public EntityDal EntityData { get; set; }
        public SecurityDal SecurityData { get; set; }
        public List<EntityDal> Entitities { get; set; }
        public List<SecurityDal> Securtities { get; set; }
    }
    public enum ThreadingUI
    {
        Initial,
        Start,
        Pause,
        Continue,
        Stop
    }
    public enum UIAction
    {
        None = 1,
        Start,
        Pause,
        Resume,
        Stop,
        RemoveItemFromSource,
        AddItemToDestination,
        PoolDBEntityReceieved,
        PoolDBSecurityReceieved,
        InProcessEntityReceieved,
        InProcessSecurityReceieved,
        SecurityProcessed,
        EntityProcessed,
        EntityDirectlyProcessed,
        SecurityReProcessed,
        EntityReProcessed,
    }
}
